package service

import (
	"fly/global"
	"fly/models"
	"fly/schema"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/logs"
	"github.com/duke-git/lancet/v2/convertor"
	"github.com/duke-git/lancet/v2/slice"
)

const (
	DeptCacheSimple = "DeptCacheSimple:%d"
	DeptCacheName   = "DeptCacheName:%d"
)

type SysDeptService struct {
	BaseService
}

// GetList 获取所有符合条件的chart
func (c *SysDeptService) GetList(filters ...CondFunc) []*models.SysDept {
	c.WhereField = append(c.WhereField, new(models.SysDept).WhereField()...)

	var orders []*models.SysDept
	qs := orm.NewOrm().QueryTable(new(models.SysDept))
	if len(c.WhereField) > 0 && len(filters) > 0 {
		cond := orm.NewCondition()
		for _, other := range filters {
			cond = other(cond)
		}
		qs = qs.SetCond(cond)
	}
	qs = qs.OrderBy("id")
	_, err := qs.All(&orders)
	if err != nil {
		return nil
	}
	return orders
}

func (c *SysDeptService) GetSubDeptIdListByUserId(userId int64) ([]int64, error) {
	user, err := models.GetSysUserById(userId)
	if err != nil {
		return nil, err
	}
	if user.IsSuperAdmin() {
		var list []*models.SysDept
		_, err := orm.NewOrm().QueryTable(new(models.SysDept)).OrderBy("sort").All(&list, "id")
		ids := slice.Map(list, func(index int, item *models.SysDept) int64 {
			return item.Id
		})
		return ids, err
	} else {
		subIds := c.GetSubDeptList(user.DeptId)
		if subIds != nil {
			subIds = append(subIds, user.DeptId)
			return subIds, nil
		}
		return []int64{user.DeptId}, nil
	}
}

// GetSubDeptList 根据id查询子部门
func (c *SysDeptService) GetSubDeptList(id int64) []int64 {
	var list []*models.SysDept
	qs := orm.NewOrm().QueryTable(new(models.SysDept)).Filter("pids__contains", id).OrderBy("sort")
	_, err := qs.All(&list, "id")
	if err != nil {
		return nil
	}
	ids := slice.Map(list, func(index int, item *models.SysDept) int64 {
		return item.Id
	})
	return ids
}

// FindAllIds ..
func (c *SysDeptService) FindAllIds(ids []int64) []*models.SysDept {
	var list []*models.SysDept
	if len(ids) == 0 {
		return list
	}
	qs := orm.NewOrm().QueryTable(new(models.SysDept)).Filter("id__in", ids)
	_, err := qs.All(&list)
	if err != nil {
		return nil
	}
	return list
}

// GetPidList ...
func (c *SysDeptService) GetPidList(pid int64) string {
	if pid == schema.RootNode {
		return convertor.ToString(schema.RootNode)
	}
	var list []*models.SysDept
	// 所有部门的id,pids
	qs := orm.NewOrm().QueryTable(new(models.SysDept))
	_, err := qs.All(&list, "id", "pids")
	if err != nil {
		logs.Error("query dept all err", err)
		return ""
	}
	allList := c.GetList()
	deptMap := make(map[int64]*models.SysDept, len(allList))
	for _, dept := range allList {
		deptMap[dept.Id] = dept
	}
	// 递归查询所有上级部门Id列表
	var pidList []int64
	c.getPidTree(pid, deptMap, &pidList)
	return slice.Join(pidList, ",")
}

// GetPidList ...
func (c *SysDeptService) getPidTree(pid int64, deptMap map[int64]*models.SysDept, pidList *[]int64) {
	if pid == schema.RootNode {
		// 无上级了
		return
	}
	parent := deptMap[pid]
	if parent != nil {
		c.getPidTree(parent.Pid, deptMap, pidList)
	}
	*pidList = append(*pidList, pid)
}

func (c *SysDeptService) GetSimpleDeptById(id int64) (*models.SysDept, error) {
	key := fmt.Sprintf(DeptCacheSimple, id)
	return global.GetCache[*models.SysDept](key, func() (*models.SysDept, error) {
		dept := models.SysDept{}
		sysDept := new(models.SysDept)
		err := orm.NewOrm().QueryTable(sysDept).Filter("id", id).One(&dept, sysDept.SimpleField()...)
		return &dept, err
	})
}

func (c *SysDeptService) GetSimpleDeptNameById(id int64) (string, error) {
	key := fmt.Sprintf(DeptCacheName, id)
	return global.GetCache[string](key, func() (string, error) {
		dept := models.SysDept{}
		err := orm.NewOrm().QueryTable(new(models.SysDept)).Filter("id", id).One(&dept, "name")
		if err != nil {
			return "", err
		}
		return dept.Name, nil
	})
}
